An Introduction to Design Patterns
00 - Table of Contents
01 - Introduction
02 - What are Design Patterns?
03 - Basic rules
04 - A Tour of Patterns
05 - Feedback
06 - Resources
07 - Acknowledgments
01 - Introduction
Nowadays, with the increasing use of advanced coding techniques, mainly for rendering engines, demos are getting more and more complex pieces of software. And not to mention that lots of sceners are using scripting engines to create their demos. When using such tools, the reusability and the flexibility of their routines is a crucial point in the making of their productions. The use of Design Patterns can help you to make better integration of your code and thus making better demos!
Many people claim that they write demos in C++ while the only features they use are the ability to declare variables "everywhere" and to overload operators for vector and matrix math. There are much more interresting things to do in C++ and the first one is pure state of the art Object Oriented Programming of course!
I know that there's a traditional taste for optimization tricks in the demo scene so I have to notify all the instruction pipeline optimization freaks that Design Patterns won't speed up their code... but that doesn't mean that they will slow it down either!
Design Patterns will only help you to build more reliable, more comprehensive and better organized Object Oriented programs. Such programs are often easier to extend and to debug than the good old C melting pot full of awful global variables and symbol cross references. :)
One might say that Design Patterns are just yet another programming paradigm invented for business application programmers and not for demo hackers but whatever you may think, Design Patterns deserves you to take a look at them because they are just interresting general programming topics...
I will assume that you already have skills in OOP with C++. It means that you have to know what the following words means : objects, classes, references, inheritence, virtual and abstract methods, interfaces, templates, ...
And when I'll have to use conventional data structures as such as table or lists, I'll use the framework provided by the ANSI C++ STL which is now considered as a standard and is freely available for GNU compilers.
Still there? Ok, here we go...
02 - What are Design Patterns?
For years now, the big programming paradigm in the OO has been: reusability. But how many times have you been able to reuse pieces of code without having to patch them or without significantly losing runtime efficiency?
Design Patterns are neither tangible pieces of code nor an analysis methodology like OMT or UML are. No, Design Patterns are much more some sort of well known and reliable solutions for several design issues that you often run into when you develop some more or less advanced objects frameworks.
Design Patterns can be grouped in three main families:
- Creational Patterns, which are used to produce new objects
- Behavioural Patterns, which influence the way objects react to events
- Structural Patterns, which define how objects are linked together
We'll often refer to Client as the class using the Design Pattern. And that's the point, Patterns are made to serve other objects, to preserve them from the initialization, behaviour and the structure of other objects.
03 - Basic rules
Before starting with the description of some Patterns, We'll describe here several rules to apply when building OO programs.
Rule 1 - Class inheritence Vs Interface inheritence
A CLASS defines the implementation of an object: its internal state and the code of its methods.
The TYPE of an object only refers to its interface: the set of queries or events it answers to.
When inheriting from several interfaces, an object CAN HAVE DIFFERENT TYPES.
Example:
class Drawable { public: virtual void draw( Surface *s ) = 0; }; class Resizable { public: virtual void resize( int w, int h ) = 0; }; class Sprite : public Drawable, Resizable { public: Sprite( Image *img, const Pixel &transparency ); // ... void draw( Surface *s ); void resize( int w, int h ); }; void foo() { vectorIn this example we have a collection of sprites objects and two lists of objects: one for the objects we'll actually rasterize on a surface and one for the objects that will be resized for some reason. The same sprite object can be referenced as much in 'to_be_displayed' as in 'to_be_resized', the same object can be viewed with different types thanks to the interfaces it implements.repository; vector to_be_displayed; vector to_be_resized; // ... }
Rule 2 - Compose, don't inherit
Inheritance is a great feature of OOP languages unless it's misused... Both aggregation and inheritance allows reusability of classes. But delegation is far more "dynamic" than inheritance and it's always possible to replace inheritance by delegation.
A good example is a simple image file loader. You could write it like this.
// Very simple image loading interface class Image_Loader { public: virtual void open( char *filename ) = 0; virtual void read( Surface *surf ) = 0; virtual void close() = 0; }; // Some classes implementing this interface class PNG_Loader : public Image_Loader { ... } ; class GIF_Loader : public Image_Loader { ... }; class JPEG_Loader : public Image_Loader { ... };When a client application will want to load an image, you'll have to write the following instruction:
Image_Loader *img_loader = new GIF_Loader; img_loader->open( "old-skool-pattern.gif" ); img_loader->read( a_surface ); img_loader->close();This means that type of the object is hardcoded in the client. In other words, the type of the object being instancied is statically defined. The right thing to do is to DELEGATE the selection of the type of loader to use to a new class containing an Image_Loader. So we add the following class to our system:
class Image_Loader_Wrapper { Image_Loader *loader; public: void open( char *filename ); void read( Surface *surf ); void close(); };All these routines will only called the appropriate method on the built-in loader object which will be instanciated to the right type by some initialization code stored in open(). And what about the new client code?
Image_Loader *img_loader = new Image_Loader_Wrapper; img_loader->open( "old-skool-pattern.gif" ); img_loader->read( a_surface ); img_loader->close();Of course we shoudln't have named our class Image_Loader_Wrapper but simply Image_Loader only because all the details of the implementation MUST be hidden to the client application.
04 - A tour of Patterns
In the other articles, we'll take a glance at some Design Patterns. If you're already an experienced OO programmer, some of them will look pretty familiar to you.
The patterns we will study are all described in the "Gang of Four" (GoF) book which refers to Erich Gamma et al Design Patterns Catalog (see Resources).
05 - Feedback
I'm looking forward to every kind of feedback... except flames from all the assembler heads out there: I really had great fun coding in pure asm programs but C++ also really makes my day.
If you found any bugs in the code or something you don't understand because of my weird English, don't hesitate to get in touch with me.
If you want to chat about this bunch of articles, OOP or demos in general.
email - brioche@linuxbe.org
06 - Resources
The following books are useful for anyone who wants to learn more about Design Patterns and OOP in general.
The C++ Programming Language, 3rd Edition.
Bjarne Stroustrup,
Addison-Wesley.
Thinking in C++.
Bruce Eckel,
Prentice-Hall.
Design Patterns, Elements of Reusable Object Oriented Software.
Erich Gamma et al.,
Addison-Wesley.
Design Patterns for Software Architectures
Wolfgang Pree,
Addison-Wesley.
A very nice place to gather informations about OOP and especially C++ is Douglas C. Shmidt's homepage: http://www.cs.wustl.edu/~schmidt
07 - Acknowledgments
I'd like to thank blackaxe/kolor (years ago) for proving me that writing object oriented demo code was possible and efficient.
Huge respect to nao, nuke, jester/sanity, reflex, rob hubbard, drax, freekzoid, martin galway and all the others for all the cool chiptunes I enjoyed to listen to while writing these documents (btw, xsidplay rocks!). And respect to rez/eclipse for putting all this hot material on-line at www.chiptune.com.
Big up to all the aspirine gangsters. Colas, for your comments! =)
Hello to everyone on the inscene2k mailing list! =)